# import pandas as pd
#
# # 1. 读取数据
# merged_df = pd.read_csv('F:/25MCM_C/C_data/summerOly_athletes.csv')  # 替换为实际文件路径
#
# # 2. 清理数据
# merged_df.columns = merged_df.columns.str.strip().str.upper()  # 清理列名
# merged_df['MEDAL'] = merged_df['MEDAL'].str.strip().str.upper()  # 清理奖牌列中的空格
#
# # 3. 统计每个国家在不同赛事中的奖牌情况
# medal_summary = merged_df.groupby(['NOC', 'EVENT', 'MEDAL']).size().unstack(fill_value=0)
##比赛结束前最后一天售后群发布无水印可视化结果+无标注代码【可直接提交】为了防止倒卖， 论文写作过程中遗留数个致命问题，无关代码，该问题解决方式仅在官网授权售后群答疑，盗卖方式购买资料不提供答疑，感谢理解 美赛资料助攻购买链接+说明https://docs.qq.com/doc/p/f3dc6bffbf4dab58dbdfd3e5e5de18a2ad974216
# # 4. 计算每个国家在不同赛事中的奖牌比率
# # 计算每个国家在每个赛事中的总奖牌数
# medal_summary['TOTAL'] = medal_summary['GOLD'] + medal_summary['SILVER'] + medal_summary['BRONZE']
#
# # 计算每个国家在每个赛事中的金牌、银牌、铜牌比率
# medal_summary['GOLD_RATIO'] = medal_summary['GOLD'] / medal_summary['TOTAL']
# medal_summary['SILVER_RATIO'] = medal_summary['SILVER'] / medal_summary['TOTAL']
# medal_summary['BRONZE_RATIO'] = medal_summary['BRONZE'] / medal_summary['TOTAL']
#
# # 5. 计算综合指标 - 可以基于奖牌数、金牌比率、总奖牌数等
# # 为每个国家评估每个赛事的重要性，可以选择不同的标准来衡量
# medal_summary['GOLD_SCORE'] = medal_summary['GOLD'] * medal_summary['GOLD_RATIO']
# medal_summary['SILVER_SCORE'] = medal_summary['SILVER'] * medal_summary['SILVER_RATIO']
# medal_summary['BRONZE_SCORE'] = medal_summary['BRONZE'] * medal_summary['BRONZE_RATIO']
##比赛结束前最后一天售后群发布无水印可视化结果+无标注代码【可直接提交】为了防止倒卖， 论文写作过程中遗留数个致命问题，无关代码，该问题解决方式仅在官网授权售后群答疑，盗卖方式购买资料不提供答疑，感谢理解 美赛资料助攻购买链接+说明https://docs.qq.com/doc/p/f3dc6bffbf4dab58dbdfd3e5e5de18a2ad974216
# # 6. 找到每个国家最重要的 3-4 个赛事
# top_events = []
# for country in medal_summary.index.get_level_values('NOC').unique():
#     country_data = medal_summary.loc[country]
#
#     # 排序得到奖牌数和奖牌比率综合指标的前3-4个赛事
#     sorted_events = country_data[['GOLD_SCORE', 'SILVER_SCORE', 'BRONZE_SCORE']].sum(axis=1).sort_values(
#         ascending=False).head(4)
#
#     # 记录每个国家最重要的3-4个项目
#     top_events.append({
#         'NOC': country,
#         'Top 3-4 Events': sorted_events.index.tolist(),
#         'Total Importance Score': sorted_events.sum()
#     })
#
# # 7. 创建包含每个国家最重要赛事的表格
# top_events_df = pd.DataFrame(top_events)
#
# # 8. 查看结果
# print(top_events_df)#比赛结束前最后一天售后群发布无水印可视化结果+无标注代码【可直接提交】为了防止倒卖， 论文写作过程中遗留数个致命问题，无关代码，该问题解决方式仅在官网授权售后群答疑，盗卖方式购买资料不提供答疑，感谢理解 美赛资料助攻购买链接+说明https://docs.qq.com/doc/p/f3dc6bffbf4dab58dbdfd3e5e5de18a2ad974216
#
# # 9. 保存结果为 CSV 文件
# top_events_df.to_csv('F:/25MCM_C/C_data/top_important_events_by_country.csv', index=False)  # 保存为新的文件

import pandas as pd
import numpy as np

# 安装shap: pip install shap
import shap

from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error

######################################################
# 1) 读取并清理数据
######################################################
df = pd.read_csv('F:/25MCM_C/C_data/merged1.csv', encoding='latin1', low_memory=False)

print("Columns:", df.columns)

# 假设 df 包含列: YEAR, NOC, SPORT, MEDAL, GOLD, SILVER, BRONZE, TOTAL, HOST, EVENTS, ...
df.columns = df.columns.str.strip().str.upper()

# 可根据实际情况将:
# - YEAR 转 int
# - GOLD, SILVER, BRONZE, TOTAL, EVENTS 转数值
for col in ['GOLD','SILVER','BRONZE','TOTAL','EVENTS']:
    if col in df.columns:
        df[col] = pd.to_numeric(df[col], errors='coerce').fillna(0)

# 标记 IS_HOST#比赛结束前最后一天售后群发布无水印可视化结果+无标注代码【可直接提交】为了防止倒卖， 论文写作过程中遗留数个致命问题，无关代码，该问题解决方式仅在官网授权售后群答疑，盗卖方式购买资料不提供答疑，感谢理解 美赛资料助攻购买链接+说明https://docs.qq.com/doc/p/f3dc6bffbf4dab58dbdfd3e5e5de18a2ad974216
if 'HOST' in df.columns:
    df['HOST'] = df['HOST'].astype(str).str.upper().str.strip()
    df['NOC']  = df['NOC'].astype(str).str.upper().str.strip()
    df['IS_HOST'] = (df['NOC'] == df['HOST']).astype(int)
else:
    df['IS_HOST'] = 0

# 目标: 假设要预测 'MEDALS' = GOLD+SILVER+BRONZE
df['MEDALS'] = df.get('MEDALS', df.get('TOTAL', df.get('GOLD', 0)+df.get('SILVER', 0)+df.get('BRONZE', 0)))
# 如果没有专门MEDALS列，可自定义:
# df['MEDALS'] = df['GOLD'] + df['SILVER'] + df['BRONZE']

# 也可把SPORT做One-Hot (若很多项目, 可能会产生很多列)
if 'SPORT' in df.columns:
    df['SPORT'] = df['SPORT'].astype(str).str.upper().str.strip()
else:
    df['SPORT'] = 'UNKNOWN'

######################################################
# 2) 构建回归模型特征
######################################################
# One-Hot encode SPORT
df_model = pd.get_dummies(df, columns=['SPORT'], prefix='SPORT')

# 选择特征 (示例)
features = []
if 'YEAR' in df_model.columns:
    features.append('YEAR')
if 'IS_HOST' in df_model.columns:
    features.append('IS_HOST')
if 'EVENTS' in df_model.columns:
    features.append('EVENTS')

# 把所有 'SPORT_XXXX' 列加进特征
sport_cols = [col for col in df_model.columns if col.startswith('SPORT_')]
features += sport_cols#比赛结束前最后一天售后群发布无水印可视化结果+无标注代码【可直接提交】为了防止倒卖， 论文写作过程中遗留数个致命问题，无关代码，该问题解决方式仅在官网授权售后群答疑，盗卖方式购买资料不提供答疑，感谢理解 美赛资料助攻购买链接+说明https://docs.qq.com/doc/p/f3dc6bffbf4dab58dbdfd3e5e5de18a2ad974216

target = 'MEDALS'

X = df_model[features].copy()
y = df_model[target].copy()

# 去掉不合法行
X.fillna(0, inplace=True)
y.fillna(0, inplace=True)

######################################################
# 3) 训练随机森林
######################################################
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2, random_state=42)

model = RandomForestRegressor(n_estimators=200, random_state=42)
model.fit(X_train, y_train)

y_pred = model.predict(X_test)
mse = mean_squared_error(y_test, y_pred)
print(f"RandomForest MSE: {mse:.3f}")

######################################################
# 4) SHAP分析(可视化+特征重要度)
######################################################
# 用 TreeExplainer
explainer = shap.TreeExplainer(model)
# 取一部分样本以加速
subset = X_test.sample(min(200, len(X_test)), random_state=42)
shap_values = explainer.shap_values(subset)

# 可视化 overall importance
shap.summary_plot(shap_values, subset, plot_type="bar", show=False)

# 也可做 summary_plot dot
shap.summary_plot(shap_values, subset, show=False)

import matplotlib.pyplot as plt
plt.savefig('shap_summary.png')
plt.close()

######################################################
# 5) 找出对"本国"影响最大的3-4个项目
######################################################
# 假设我们想针对一个特定国家, e.g. "CHN",
# 分析X_test里 NOC="CHN" 的样本(需在df_model保留NOC?),
# 并计算SPORT_xxx特征的平均abs shap value
#
# 若df_model不保留NOC,则需另外的df_test index对齐
# => 这里演示思路, 不可直接运行, 需保留NOC

# (A) 先对X_test做 index->(NOC, Year, Sport) or keep an alignment
#   这里假设我们在 df 同样index 做train_test_split,
#   并df['NOC']保留:
df['INDEX'] = range(len(df))  # 给df一个绝对index
df_model['INDEX'] = df['INDEX']  # 同步
X_train, X_test, y_train, y_test = train_test_split(df_model, y, test_size=0.2, random_state=42)

# 重新训练(简略)
X_train2 = X_train[features]
y_train2 = y_train
model2 = RandomForestRegressor(n_estimators=200, random_state=42)
model2.fit(X_train2, y_train2)

# shap
subset = X_test.sample(min(200, len(X_test)), random_state=42)
explainer2 = shap.TreeExplainer(model2)
shap_values2 = explainer2.shap_values(subset[features])


test_merge = pd.merge(
    subset[['INDEX']],   # keep the same index
    df[['INDEX','NOC']], on='INDEX', how='left'
)

test_merge['ABS_SHAP'] = np.abs(shap_values2).sum(axis=1)

SPORT_indices = [i for i,col in enumerate(features) if col.startswith('SPORT_')]
test_merge['SPORT_SHAP_SUM'] = np.abs(shap_values2[:, SPORT_indices]).sum(axis=1)

# 仅保留 NOC="CHN"
chn_df = test_merge[test_merge['NOC']=='CHN'].copy()

# 取 shap_values2 里 CHN对应的行
# => chn_shap = shap_values2[chn_df index in subset],
#    需要 index对齐, 这里演示

chn_indices = chn_df.index.values  # 这在subset index
chn_shap   = shap_values2[chn_indices,:]

# 统计每个SPORT_xxx列对CHN的平均绝对 shap
mean_abs_shap = {}
for i,col in enumerate(features):
    if col.startswith('SPORT_'):
        mean_abs_shap[col] = np.mean(np.abs(chn_shap[:,i]))

# 排序取top 3-4
top_sports = sorted(mean_abs_shap.items(), key=lambda x:-x[1])[:4]

print("For CHN, top 3-4 sports that influence medals the most (based on shap):")
for sport, val in top_sports:
    # sport 形如 "SPORT_BASKETBALL"
    print(f"{sport} => shap contribution={val:.4f}")

# => 这样可针对每个国家循环, 并输出top sports


"""
加权
"""
# import pandas as pd
#
# # 1. 读取数据（例如保留Medal、Gold、Silver、Bronze列等）
# merged_df = pd.read_csv('F:/25MCM_C/C_data/summerOly_athletes.csv', encoding='latin1')
#
# # 2. 清理数据
# merged_df.columns = merged_df.columns.str.strip().str.upper()  # 列名大写
# merged_df['MEDAL'] = merged_df['MEDAL'].str.strip().str.upper()  # 奖牌
#
# # 确保如GOLD/SILVER/BRONZE列存在则转为数值(如果有)
# for col in ['GOLD','SILVER','BRONZE']:
#     if col in merged_df.columns:
#         merged_df[col] = pd.to_numeric(merged_df[col], errors='coerce').fillna(0)
#
# # 3. 统计每个国家在不同"Event"（或Sport/Event）上的奖牌情况
# #    如果没有Gold/Silver/Bronze列, 可以基于MEDAL列分组统计.
# medal_summary = merged_df.groupby(['NOC', 'EVENT', 'MEDAL']).size().unstack(fill_value=0)
#
# # 如果 MEDAL 列中包含 "GOLD","SILVER","BRONZE","NO MEDAL" 等，需要看看 unstack 后的列有哪些
# medal_cols = medal_summary.columns.tolist()  # e.g. ['BRONZE','GOLD','NO MEDAL','SILVER']
#
# # 4. 计算每个国家在每个赛事中的总奖牌数 (只要 Gold/Silver/Bronze 三列存在)
# #    如果 unstack 后出现 'NO MEDAL' 也在列里，可以进行区分.
# def safe_col(df, colname):
#     return df[colname] if colname in df.columns else 0
#
# medal_summary['GOLD']   = safe_col(medal_summary, 'GOLD')
# medal_summary['SILVER'] = safe_col(medal_summary, 'SILVER')
# medal_summary['BRONZE'] = safe_col(medal_summary, 'BRONZE')
#
# medal_summary['TOTAL'] = medal_summary['GOLD'] + medal_summary['SILVER'] + medal_summary['BRONZE']
#
# # 5. "加权得分"：例如 Gold*3 + Silver*2 + Bronze*1
# medal_summary['WEIGHTED_SCORE'] = (3*medal_summary['GOLD'] +
#                                    2*medal_summary['SILVER'] +
#                                    1*medal_summary['BRONZE'])
#
# # 如果您想用比率, 也可以加 ratio = Weighted_Score / sum(Weighted_Score of this country?)
#
# # 6. 找到每个国家最重要的 3-4 个赛事(基于加权得分)
# top_events = []
# for country in medal_summary.index.get_level_values('NOC').unique():
#     # 取该国数据
#     country_data = medal_summary.loc[country]
#     # 排序: Weighted_SCORE从大到小
#     sorted_events = country_data['WEIGHTED_SCORE'].sort_values(ascending=False)
#     top_3_4 = sorted_events.head(4)
#
#     top_events.append({
#         'NOC': country,
#         'TopEvents': top_3_4.index.tolist(),
#         'Score': top_3_4.values.tolist()
#     })
#
# top_events_df = pd.DataFrame(top_events)
#
# # 7. 输出结果#比赛结束前最后一天售后群发布无水印可视化结果+无标注代码【可直接提交】为了防止倒卖， 论文写作过程中遗留数个致命问题，无关代码，该问题解决方式仅在官网授权售后群答疑，盗卖方式购买资料不提供答疑，感谢理解 美赛资料助攻购买链接+说明https://docs.qq.com/doc/p/f3dc6bffbf4dab58dbdfd3e5e5de18a2ad974216
# print(top_events_df)
# top_events_df.to_csv('F:/25MCM_C/C_data/top_important_events_by_country.csv', index=False)
# print("Done. Saved to top_important_events_by_country.csv")
